﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
using UnityEngine;
#if UNITY_EDITOR
#endif
namespace MainScene
{
    [Serializable]
    public class MonsterAIInfo
    {
        [XmlAttribute("showInMiniMap")]
        public bool showInMiniMap = true;
        [XmlAttribute("showBossEffect")]
        public bool showBossEffect;
        [XmlAttribute("monsterGroup")]
        public int monsterGroup;
#if UNITY_EDITOR
#endif
        [XmlAttribute("modelId")]
        public int modelId;
        [XmlAttribute("aiType")]
        public int aiType;
        [XmlAttribute("isNpc")]
        public bool isNpc = false;
        [XmlAttribute("aiEnable")]
        public bool aiEnable = true;
        [XmlAttribute("wanderRadius")]
        public float wanderRadius;
        [XmlAttribute("pursueRadius")]
        public float pursueRadius;
        [XmlAttribute("wanderSpeed")]
        public float wanderSpeed;
        [XmlAttribute("pursueSpeed")]
        public float pursueSpeed;
        [XmlAttribute("rotateSpeed")]
        public float rotateSpeed;
        [XmlAttribute("restTime")]
        public float restTime;
        [XmlAttribute("lastPathIndex")]
        public int lastPathIndex = -1;
        [XmlAttribute("currentPathIndex")]
        public int currentPathIndex = 0;
        //场景默认动作
        [XmlAttribute("stand")]
        public string defultAni = "stand";
        [XmlAttribute("EnableClickDialog")]
        public bool EnableClickDialog = false;
        [XmlAttribute("ClickDialogId")]
        public int ClickDialogId = -1;
        [XmlAttribute("stopDistance")]
        public int stopDistance = 1;
        [XmlAttribute("defultUseOffset")]
        public bool defultUseOffset = false;
        //往返怪 路径点
        public List<string> pathNode = new List<string>();
        public MonsterAIInfo() { }
        public MonsterAIInfo(int modelId, int aiType, float wanderRadius,
            float pursueRadius, float wanderSpeed, float pursueSpeed, float rotateSpeed, float restTime, bool aiEnable, bool showBossEffect, bool isNpc, bool EnableClickDialog, int clickDialog)
        {
            this.showInMiniMap = true;
            this.EnableClickDialog = EnableClickDialog;
            this.ClickDialogId = clickDialog;
            this.isNpc = isNpc;
            this.modelId = modelId;
            this.aiType = aiType;
            this.wanderRadius = wanderRadius;
            this.pursueRadius = pursueRadius;
            this.wanderSpeed = wanderSpeed;
            this.pursueSpeed = pursueSpeed;
            this.rotateSpeed = rotateSpeed;
            this.restTime = restTime;
            this.aiEnable = aiEnable;
            this.showBossEffect = showBossEffect;
        }

#if UNITY_EDITOR
        [XmlIgnore]
        public Action ModelValueChange;
        public void ModelValueChangeFuc()
        {
            if (ModelValueChange != null)
            {
                ModelValueChange();
            }
        }
        [XmlIgnore]
        public Action AnimValueChangeCall;
        public void AnimValueChange()
        {
            if (AnimValueChangeCall != null)
            {
                AnimValueChangeCall();
            }
        }
#endif

    }
    //场景数据存储结构
    [Serializable]
    public class UnitData : ObjectData
    {
        public MonsterAIInfo unitExtrInfo;
        /// <summary>
        /// 编辑器下手动调用后 调用函数赋值
        /// </summary>
        public UnitData()
        {
            objectType = (int)SceneObjType.Unit;
            visible = false;
        }

        public void SetPrefabName(int modelId, SceneUnitAI aiType)
        {
        }
    }

    public enum StaticUnitType
    {
        StaticUnit,
        ClickArea,
        SceneEffectAchor
    }

    /// <summary>
    /// 风墙
    /// </summary>
    [Serializable]
    public class DoorData : ObjectData
    {
        //空气墙直接做一个, collider 预设
        [XmlAttribute("prefabName")]
        public string prefabName;

        [XmlAttribute("isDoor")]
        public bool isDoor = true;

        [XmlAttribute("x1")]
        public float x1;
        [XmlAttribute("y1")]
        public float y1;
        [XmlAttribute("z1")]
        public float z1;

        [XmlAttribute("x2")]
        public float x2;
        [XmlAttribute("y2")]
        public float y2;
        [XmlAttribute("z2")]
        public float z2;

        [XmlAttribute("x3")]
        public float x3;
        [XmlAttribute("y3")]
        public float y3;
        [XmlAttribute("z3")]
        public float z3;

        [XmlAttribute("x4")]
        public float x4;
        [XmlAttribute("y4")]
        public float y4;
        [XmlAttribute("z4")]
        public float z4;

        [XmlAttribute("sizeX")]
        public float sizeX;
        [XmlAttribute("sizey")]
        public float sizey;
        [XmlAttribute("sizez")]
        public float sizez;
        [XmlAttribute("useDefultOffset")]
        public bool useDefultOffset;

        [XmlAttribute("StaticObjType")]
        public int staticObjType;
        public DoorData()
        {
            objectType = (int)SceneObjType.Door;
            visible = false;
        }

    }


    /// <summary>
    /// 宝箱的模型资源目前只有一个，不做配置处理
    /// 
    /// </summary>
    [Serializable]
    public class BoxData : ObjectData
    {
        //对应服务器 识别id 
        [XmlAttribute("serverId")]
        public int serverId;
        [XmlAttribute("modelId")]
        public int modelId = 15;
        [XmlAttribute("isOpen")]
        public bool isOpen;
        public BoxData()
        {
            objectType = (int)SceneObjType.Box;
            visible = true;
        }

        public void SetUniqueData(int serverId, bool isOpen, int modelId)
        {
            this.modelId = modelId;
            this.serverId = serverId;
            this.isOpen = isOpen;
        }
    }

    /// <summary>
    /// 采集资源
    /// </summary>
    [Serializable]
    public class ResourcesData : ObjectData
    {
        [XmlAttribute("excelID")]
        public int excelID;
        [XmlAttribute("modelId")]
        public int modelId;//资源模型Id
        [XmlAttribute("resourcesType")]
        public int resourcesType; // 资源类型
        public ResourcesData()
        {
            objectType = (int)SceneObjType.Resources;
            visible = true;
        }
        public void SetModelData(int modelId, int excelID, int resType)
        {
            this.modelId = modelId;
            this.resourcesType = resType;
            this.excelID = excelID;
        }
    }

    public enum SceneDamageAreaType
    {
        CircleDamageArea = 0,
        Rectangular = 1
    }

    [Serializable]
    public class DamageAreaSpawnData : ObjectData
    {
        public DamageAreaData damageModel;
        [XmlAttribute("size_x")]
        public float size_x = 1;
        [XmlAttribute("size_y")]
        public float size_y = 1;
        [XmlAttribute("size_z")]
        public float size_z = 1;
        [XmlAttribute("circleRange")]
        public float circleRange;
        [XmlAttribute("spawnCount")]
        public int spawnCount;
        [XmlAttribute("intervalTime")]
        public float intervalTime;
        [XmlAttribute("startRectValue")]
        public float startRectValue;
        [XmlAttribute("EndRectValue")]
        public float EndRectValue;
        public DamageAreaSpawnData()
        {
            objectType = (int)SceneObjType.DamageAreaSpawn;
            visible = true;
        }
        public void SetDamageData(DamageAreaData data, float circle,
            int spawnCout, float intervalTime,
            float x, float y, float z,
            float startRectValue, float EndRectValue)
        {
            this.startRectValue = startRectValue;
            this.EndRectValue = EndRectValue;
            this.damageModel = data;
            this.circleRange = circle;
            this.spawnCount = spawnCout;
            this.intervalTime = intervalTime;
            this.size_x = x;
            this.size_y = y;
            this.size_z = z;
        }
    }

    /// <summary>
    /// 场景伤害区域
    /// </summary>
    [Serializable]
    public class DamageAreaData : ObjectData
    {
        [XmlAttribute("lifeSpan")]
        public float lifeSpan = 0;//存在时间 : <= 0 一直存在 ， >0 时间到后自动销毁
        [XmlAttribute("areaType")]
        public int areaType = 1; //场景区域伤害范围类型
        [XmlAttribute("size_x")]
        public float size_x = 1;
        [XmlAttribute("size_y")]
        public float size_y = 1;
        [XmlAttribute("size_z")]
        public float size_z = 1;
        [XmlAttribute("Radius")]
        public float Radius = 1;
        [XmlAttribute("DisplayFrequency")]
        public float DisplayFrequency = 0;//显示频率
        [XmlAttribute("SimpleModelId")]
        public int SimpleModelId = 0;
        [XmlAttribute("FrequencyEffectId")]
        public int FrequencyEffectId = 0;
        //区域伤害逻辑
        [XmlAttribute("buffId")]
        public int buffId;
        [XmlAttribute("warningFrameTime")]
        public float warningFrameTime = 0;
        [XmlAttribute("warningFrameEffectId")]
        public int warningFrameEffectId = 0;
        [XmlAttribute("areaDamageEnableTime")]
        public float areaDamageEnableTime = 0;
        [XmlAttribute("areaDamageEnableInteral")]
        public float areaDamageEnableInteral = 0;

        public TransformEx FrequencyEffectRoot;
        public DamageAreaData()
        {
            objectType = (int)SceneObjType.DamageArea;
            visible = true;
        }
        public DamageAreaData Clone(Vector3 pos, string objectId)
        {
            var clone = new DamageAreaData();
            clone.posX = pos.x;
            clone.posY = pos.y;
            clone.posZ = pos.z;
            clone.objectId = objectId;
            clone.objectType = objectType;
            clone.visible = visible;
            clone.rotX = rotX;
            clone.rotY = rotY;
            clone.rotZ = rotZ;

            clone.SetAreaSize(size_x, size_y, size_z, Radius,
            areaType == (int)SceneDamageAreaType.CircleDamageArea, DisplayFrequency, SimpleModelId,
            buffId, lifeSpan, FrequencyEffectId,
            areaDamageEnableTime, areaDamageEnableInteral, warningFrameEffectId, warningFrameTime, FrequencyEffectRoot);
            return clone;
        }
        public void SetAreaSize(float x, float y, float z, float radius,
            bool circle, float freq, int simpleModelId,
            int buffId, float lifeSpan, int frequencyEffectId,
            float areaDamageEnableTime, float areaDamageEnableInteral,
            int warningFrameEffectId, float warningFrameTime, TransformEx freqEffectRoot)
        {
            this.size_x = x;
            this.size_y = y;
            this.size_z = z;
            this.Radius = radius;
            this.areaType = circle ? (int)SceneDamageAreaType.CircleDamageArea : (int)SceneDamageAreaType.Rectangular;
            this.DisplayFrequency = freq;
            this.SimpleModelId = simpleModelId;
            this.buffId = buffId;
            this.lifeSpan = lifeSpan;
            this.FrequencyEffectId = frequencyEffectId;
            this.areaDamageEnableTime = areaDamageEnableTime;
            this.areaDamageEnableInteral = areaDamageEnableInteral;
            this.warningFrameTime = warningFrameTime;
            this.warningFrameEffectId = warningFrameEffectId;
            this.FrequencyEffectRoot = freqEffectRoot;
        }
    }


    /// <summary>
    /// 区域触发数据
    /// </summary>
    [Serializable]
    public class AreaData : ObjectData
    {
        [XmlAttribute("sizeX")]
        public float sizeX;
        [XmlAttribute("sizeY")]
        public float sizeY;
        [XmlAttribute("sizeZ")]
        public float sizeZ;
        [XmlAttribute("radius")]
        public float radius;
        [XmlAttribute("isCircle")]
        public bool isCircle;
        public AreaData()
        {
            objectType = (int)SceneObjType.Area;
            visible = true;
        }

        public void SetAreaSize(float x, float y, float z, float radius, bool isCircle)
        {
            this.radius = radius;
            this.sizeX = x;
            this.sizeY = y;
            this.sizeZ = z;
            this.isCircle = isCircle;
        }
    }

    /// <summary>
    /// 摄像机轨迹路径
    /// </summary>
    [Serializable]
    public class SimpleCameraTrackData : ObjectData
    {
        [XmlAttribute("sizeX")]
        public float sizeX;
        [XmlAttribute("sizeY")]
        public float sizeY;
        [XmlAttribute("sizeZ")]
        public float sizeZ;

        [XmlAttribute("startPosX")]
        public float startPosX;
        [XmlAttribute("startPosY")]
        public float startPosY;
        [XmlAttribute("startPosZ")]
        public float startPosZ;

        [XmlAttribute("endPosX")]
        public float endPosX;
        [XmlAttribute("endPosY")]
        public float endPosY;
        [XmlAttribute("endPosZ")]
        public float endPosZ;

        [XmlAttribute("finalCameraPosX")]
        public float finalCameraPosX;
        [XmlAttribute("finalCameraPosY")]
        public float finalCameraPosY;
        [XmlAttribute("finalCameraPosZ")]
        public float finalCameraPosZ;

        [XmlAttribute("triggerType")]
        public int triggerType;

        public SimpleCameraTrackData()
        {
            objectType = (int)SceneObjType.SimpleCameraTrack;
            triggerType = 0;
            visible = true;
        }


        public void SetAreaSize(float x, float y, float z)
        {
            sizeX = x;
            sizeY = y;
            sizeZ = z;
        }

        public void SetStartPos(float x, float y, float z)
        {
            startPosX = x;
            startPosY = y;
            startPosZ = z;
        }
        public void SetEndPos(float x, float y, float z)
        {
            endPosX = x;
            endPosY = y;
            endPosZ = z;
        }
        public void SetFinalCameraPos(float x, float y, float z)
        {
            finalCameraPosX = x;
            finalCameraPosY = y;
            finalCameraPosZ = z;
        }
    }

    /// <summary>
    /// 单类型出生点配置数据(出生的怪物行为都是一样的)
    /// </summary>
    [Serializable]
    public class SpawnPointData : ObjectData
    {
        [XmlAttribute("diffLevel")]
        public int diffLevel;
        [XmlAttribute("poolIndex")]
        public int poolIndex;
        [XmlAttribute("startAction")]
        public string startAction;
        [XmlAttribute("cellId")]
        public string cellId;

        public MonsterAIInfo unitExtrInfo = new MonsterAIInfo();
        public SpawnPointData()
        {
            objectType = (int)SceneObjType.SpawnPoint;
            visible = true;
        }

        public void SetSpawnPointInfo(int diffLevel, int poolIndex,
                                        string startAction, string cellId,
                                        MonsterAIInfo unitextrInfo)
        {
            this.diffLevel = diffLevel;
            this.poolIndex = poolIndex;
            this.startAction = startAction;
            this.cellId = cellId;
            this.unitExtrInfo = unitextrInfo;
        }
    }

    /// <summary>
    /// 可配置一个出身点的 怪的不同行为
    /// </summary>
    [Serializable]
    public class SpawnPointExData : ObjectData
    {
        [System.Serializable]
        public class SpawnInfoTest
        {
            [XmlAttribute("aiStatus")]
            public int aiStatus;
            [XmlAttribute("diffLevel")]
            public int diffLevel;
            [XmlAttribute("poolIndex")]
            public int poolIndex;
            [XmlAttribute("ratio")]
            public int ratio;
            [XmlAttribute("startAction")]
            public string startAction;

            public SpawnInfoTest()
            { }
            public SpawnInfoTest(int aiStatus, int diffLevel, int poolIndex, int ratio, string startAction)
            {
                this.aiStatus = aiStatus;
                this.diffLevel = diffLevel;
                this.poolIndex = poolIndex;
                this.startAction = startAction;
                this.ratio = ratio;
            }
        };
        [System.Serializable]
        public class SpawnInfo
        {
            [XmlAttribute("aiStatus")]
            public int aiStatus;
            [XmlAttribute("diffLevel")]
            public int diffLevel;
            [XmlAttribute("poolIndex")]
            public int poolIndex;
            [XmlAttribute("ratio")]
            public int ratio;
            [XmlAttribute("startAction")]
            public string startAction;

            public SpawnInfo()
            { }
            public SpawnInfo(int aiStatus, int diffLevel, int poolIndex, int ratio, string startAction)
            {
                this.aiStatus = aiStatus;
                this.diffLevel = diffLevel;
                this.poolIndex = poolIndex;
                this.startAction = startAction;
                this.ratio = ratio;
            }
        };

        [XmlAttribute("cellId")]
        public string cellId;
        [XmlAttribute("delay")]
        public float delay = 0.0f;
        [XmlAttribute("loopTime")]
        public float loopTime = 1;
        [XmlAttribute("totalSpawn")]
        public int totalSpawn = 1;
        public List<SpawnInfo> spawnInfoListTest = new List<SpawnInfo>();
        public List<SpawnInfo> spawnInfoList;

        public SpawnPointExData()
        {
            objectType = (int)SceneObjType.SpawnPointEx;
            visible = true;
        }

        public void SetSpawnPointInfo(List<SpawnInfo> spawnInfoList, string cellId, float delay, float loopTime, int totalSpawn)
        {
            this.spawnInfoList = spawnInfoList;
            this.cellId = cellId;
            this.delay = delay;
            this.loopTime = loopTime;
            this.totalSpawn = totalSpawn;
        }
    }


    [Serializable]
    public class CameraData : ObjectData
    {
        public CameraData()
        {
            objectType = (int)SceneObjType.Camera;
            visible = true;
        }
    }

    [System.Serializable]
    public class Vector3Ex
    {
        [XmlAttribute("x")]
        public float x;
        [XmlAttribute("y")]
        public float y;
        [XmlAttribute("z")]
        public float z;
        public Vector3Ex() { }
        public Vector3Ex(UnityEngine.Vector3 vec)
        {
            x = vec.x;
            y = vec.y;
            z = vec.z;
        }
        public Vector3Ex(float x, float y, float z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public void UpdateValue(Vector3 value)
        {
            x = value.x;
            y = value.y;
            z = value.z;
        }
        public UnityEngine.Vector3 GetVec3()
        {
            return new Vector3(x, y, z);
        }
        public Vector3Ex Clone()
        {
            return new Vector3Ex(x, y, z);
        }
    }

    [System.Serializable]
    public class TransformEx
    {
        //[XmlAttribute("worldPos")]
        public Vector3Ex worldPos;
        //[XmlAttribute("rot")]
        public Vector3Ex rot;
        //[XmlAttribute("scale")]
        public Vector3Ex scale;
        public TransformEx() { }
        public TransformEx(Transform trans)
        {
            worldPos = new Vector3Ex(trans.position);
            rot = new Vector3Ex(trans.rotation.eulerAngles);
            scale = new Vector3Ex(trans.localScale);
        }
        public TransformEx Clone()
        {
            var temp = new TransformEx();
            temp.worldPos = worldPos.Clone();
            temp.rot = rot.Clone();
            temp.scale = rot.Clone();
            return temp;
        }
    }

    [System.Serializable]
    public class ScanningUnitData : ObjectData
    {
        [XmlAttribute("ScanningType")]
        public int ScanningType;
        [XmlAttribute("scanningInterval")]
        public float scanningInterval;
        [XmlAttribute("scanningSpeed")]
        public float scanningSpeed;
        public TransformEx Root;
        public TransformEx EffectRoot;
        public TransformEx BoxRoot;

        public Vector3Ex startForward;
        public Vector3Ex endForward;
        public TransformEx EffectPianRoot;
        [XmlAttribute("EffectPath")]
        public string EffectPath;
        [XmlAttribute("EffectPainPath")]
        public string EffectPianPath;
        public ScanningUnitData()
        {
            objectType = (int)SceneObjType.ScanningUnit;
            visible = true;
        }

        public void SetScanningUnitData(Transform root, Transform effectRoot, Transform boxRoot, Transform effectPianRoot,
            float scanningInterval, int scanningType, float scanningSpeed,
            Vector3Ex startForward, Vector3Ex endForward, string EffectPath, string EffectPianPath)
        {
            this.Root = new TransformEx(root);
            this.EffectRoot = new TransformEx(effectRoot);
            this.BoxRoot = new TransformEx(boxRoot);
            this.EffectPianRoot = new TransformEx(effectPianRoot);
            this.scanningInterval = scanningInterval;
            this.ScanningType = scanningType;
            this.scanningSpeed = scanningSpeed;
            this.startForward = startForward;
            this.endForward = endForward;
            this.EffectPath = EffectPath;
            this.EffectPianPath = EffectPianPath;
        }

        public void SetScanningUnitData(ScanningUnitData originData)
        {
            Root = originData.Root.Clone();
            EffectRoot = originData.EffectRoot.Clone();
            BoxRoot = originData.BoxRoot.Clone();
            EffectPianRoot = originData.EffectPianRoot.Clone();
            ScanningType = originData.ScanningType;
            scanningInterval = originData.scanningInterval;
            scanningSpeed = originData.scanningSpeed;
            startForward = originData.startForward.Clone();
            endForward = originData.endForward.Clone();
            this.EffectPath = originData.EffectPath;
            this.EffectPianPath = originData.EffectPianPath;
        }
    }

    [Serializable]
    public class PathNodeData : ObjectData
    {
        public PathNodeData()
        {
            objectType = (int)SceneObjType.PathNode;
            visible = true;
        }
    }

    [XmlInclude(typeof(LevelPlayerSettingData))]
    [Serializable]
    public class LevelMapRangeData : ObjectData
    {
        public LevelMapRangeData()
        {
            objectType = (int)SceneObjType.LevelMapRange;
            visible = true;
        }

        [XmlArray("doors_data")]
        [XmlArrayItem("ItemData")]
        public List<DoorData> doors_data;

        [XmlElement(Type = typeof(LevelPlayerSettingData), ElementName = "LocalPlayer")]
        public LevelPlayerSettingData localPlayer_data;
        //public 
    }

    [Serializable]
    public class LevelPlayerSettingData : UnitData
    {
        [XmlAttribute("cameraPosX")]
        public float cameraPosX;
        [XmlAttribute("cameraPosY")]
        public float cameraPosY;
        [XmlAttribute("cameraPosZ")]
        public float cameraPosZ;
        [XmlAttribute("cameraView")]
        public float cameraView;
        [XmlAttribute("specaleModelId")]
        public int specaleModelId;
        [XmlAttribute("useCallon")]
        public bool useCallon = true;
        public LevelPlayerSettingData()
        {
            objectType = (int)SceneObjType.LevelMapRange;
        }
    }

}